import React, { useEffect, useRef } from "react"
import { Image, Input, Text, View, Picker, Button } from "@tarojs/components"
import Taro from "@tarojs/taro"
import GpContainer from "@/components/GpContainer"
import { ArrowRight } from "@taroify/icons"
import clsx from "clsx"
import {
  getAreaOptions,
  getCurrentUserInfo,
  getProjectOptions,
  updateUserInfo,
  uploadV4
} from "@/apis/yikao-community"
import { useAppDispatch, useAppSelector } from "@/store/hook"
import { useSetState } from "@/utils/hooks"
import { genderMap } from "@/types/enum"
import styles from "./index.module.scss"
import { loginByPhone } from "@/store/actions/auth"
import { yearOptions } from "@/constants/words"
import { requestIsFullfilled } from "@/utils/request"
import auditStyles from "@/styles/common/audit.module.scss"

type IState = IApiRelative.IUpdateUserInfo.IParams & {
  genderText?: string
  yearText?: string
  projectValue?: number
  projectOptions: IOptionLike<number>[]
  projectName?: string
  areaOptions: [IApiRelative.IGetAreaOptions.IArea[], IApiRelative.IGetAreaOptions.IArea[]]
  areaValue?: [number, number]
  pendingAreaValue?: [number, number]
  areaName?: string
  auditStatusJson?: IUserInfo["auditStatusJson"] | null
}

const yearTexts = yearOptions.map(l => l.label)
export default function EditInfo() {
  const dispatch = useAppDispatch()
  const userInfo = useAppSelector(state => state.auth.userInfo)
  const areaDataRef = useRef<IApiRelative.IGetAreaOptions.IResData>([])
  const [state, setState] = useSetState<IState>({
    areaId: userInfo.areaId,
    areaName: userInfo.areaName,
    backgroundImage: userInfo.backgroundImage,
    description: userInfo.description,
    gender: userInfo.gender,
    genderText: genderMap.get(userInfo.gender as number),
    headImage: userInfo.headImage,
    mobile: userInfo.mobile,
    nickName: userInfo.nickName,
    projectId: userInfo.projectId,
    projectValue: void 0,
    projectName: userInfo.projectName,
    year: userInfo.year,
    yearText: yearOptions.find(l => l.value === userInfo.year)?.label,
    projectOptions: [],
    areaOptions: [[], []],
    areaValue: [0, 0],
    pendingAreaValue: [0, 0],
    auditStatusJson: null
  })
  useEffect(() => {
    fetchEditInfo()
    fetchSubjectOpions()
    fetchAreaData()
  }, [])
  function fetchEditInfo() {
    return getCurrentUserInfo({ isAuditData: true }).then(res => {
      if (requestIsFullfilled(res)) {
        const { backgroundImage, headImage, auditStatusJson } = res.data.data
        setState({
          backgroundImage,
          headImage,
          auditStatusJson
        })
      }
    })
  }
  function fetchSubjectOpions() {
    return getProjectOptions().then(data => {
      if (data && data.data && data.data.success) {
        // 过滤 综合 选项
        data.data.data = data.data.data.filter(l => l.value !== 3)
        const index = data.data.data.findIndex(l => l.value === state.projectId)
        setState({
          projectOptions: data.data.data,
          projectValue: index === -1 ? void 0 : index
        })
      }
    })
  }
  function fetchAreaData() {
    getAreaOptions().then(data => {
      if (data && data.data && data.data.success) {
        areaDataRef.current = data.data.data
        const areaIndex = [0, 0] as [number, number]
        const areaOptions = [[], []] as [
          IApiRelative.IGetAreaOptions.IArea[],
          IApiRelative.IGetAreaOptions.IArea[]
        ]
        if (state.areaId && state.areaId !== "000000") {
          const provinceId = state.areaId.slice(0, 2) + "0000"
          const provinceIndex = data.data.data.findIndex(l => l.value === provinceId)
          areaIndex[0] = provinceIndex
          const cityIndex = data.data.data[provinceIndex].children.findIndex(
            l => l.value === state.areaId
          )
          areaIndex[1] = cityIndex
        }
        areaOptions[0] = data.data.data
        areaOptions[1] = data.data.data[areaIndex[0]].children
        setState({
          areaOptions,
          areaValue: areaIndex,
          pendingAreaValue: areaIndex
        })
      }
    })
  }
  function handleTapGender() {
    Taro.showActionSheet({
      itemList: ["暂不公布", "男", "女"],
      success: function (res) {
        setState({
          gender: res.tapIndex,
          genderText: genderMap.get(res.tapIndex)
        })
      }
    })
  }
  function handleTapYears() {
    Taro.showActionSheet({
      itemList: yearTexts,
      success(result) {
        const current = yearOptions[result.tapIndex]
        setState({
          year: current.value,
          yearText: current.label
        })
      }
    })
  }
  function handleProjectChange(index) {
    setState({
      projectValue: index,
      projectId: state.projectOptions[index].value,
      projectName: state.projectOptions[index].label
    })
  }
  function handleGetPhoneNumber(ev) {
    if (ev.detail.errMsg === "getPhoneNumber:ok") {
      const code = ev.detail.code
      dispatch(loginByPhone({ code, data: ev.detail.encryptedData, iv: ev.detail.iv }) as any).then(
        ({ mobile }: IUserInfo) => {
          setState({
            mobile
          })
        }
      )
    }
  }
  function handleUpload(stateKey: keyof IState, cropScale: keyof Taro.cropImage.CropScale) {
    Taro.chooseImage({
      count: 1,
      async success(result) {
        let filepath = result.tempFilePaths[0]
        try {
          filepath = await cropImageAction(filepath, cropScale)
        } catch (error) {
          // 裁剪失败 回退到直接上传
          console.info("裁剪失败 回退到直接上传", error)
        }
        uploadV4(filepath).then(res => {
          if (res.data) {
            const resData = JSON.parse(res.data)
            if (resData.success) {
              setState({
                [stateKey]: resData.data.image
              })
            }
          }
        })
      }
    })
  }
  function cropImageAction(src: string, cropScale: keyof Taro.cropImage.CropScale) {
    return new Promise<string>((resolve, fail) => {
      Taro.cropImage({
        src,
        cropScale,
        success(result) {
          resolve(result.tempFilePath)
        },
        fail
      })
    })
  }
  function handleAreaChange(ev) {
    const { value } = ev.detail
    const { value: areaId, title } = state.areaOptions[0][value[0]].children[value[1]]
    const areaName = state.areaOptions[0][value[0]].title + "-" + title
    setState({
      areaValue: state.pendingAreaValue,
      areaId,
      areaName
    })
  }
  function handleAreaColumnChange(ev) {
    const { column, value } = ev.detail
    if (column === 0) {
      const _areaOptions = state.areaOptions.concat() as [
        IApiRelative.IGetAreaOptions.IArea[],
        IApiRelative.IGetAreaOptions.IArea[]
      ]
      _areaOptions[1] = _areaOptions[0][value].children
      setState({
        areaOptions: _areaOptions,
        pendingAreaValue: [value, 0]
      })
    } else if (column === 1) {
      setState({
        pendingAreaValue: [state.pendingAreaValue![0], value]
      })
    }
  }
  function handleAreaCancel() {
    const areaOptions = state.areaOptions.concat() as [
      IApiRelative.IGetAreaOptions.IArea[],
      IApiRelative.IGetAreaOptions.IArea[]
    ]
    const column1 = state.areaValue![0]
    areaOptions[1] = areaOptions[0][column1].children
    setState({
      pendingAreaValue: state.areaValue,
      areaOptions
    })
  }
  function handleSave() {
    const params: IApiRelative.IUpdateUserInfo.IParams = {}
    if (state.headImage) {
      params.headImage = state.headImage
    }
    if (state.nickName) {
      params.nickName = state.nickName
    }
    if (typeof state.gender === "number") {
      params.gender = state.gender
    }
    if (state.description) {
      params.description = state.description
    }
    if (state.year) {
      params.year = state.year
    }
    if (state.areaId) {
      params.areaId = state.areaId
    }
    if (state.projectId) {
      params.projectId = state.projectId
    }
    if (state.mobile) {
      params.mobile = state.mobile
    }
    if (state.backgroundImage) {
      params.backgroundImage = state.backgroundImage
    }
    Taro.showLoading({
      title: "正在保存..."
    })
    updateUserInfo(params).then(res => {
      if (res.data && res.data.success) {
        Taro.hideLoading()
        Taro.showToast({
          title: "保存成功",
          icon: "none"
        })
        Taro.navigateBack()
      }
    })
  }
  return (
    <GpContainer
      pageGap={120}
      className="min-h-screen"
      style={{
        backgroundColor: "#ffffff"
      }}
    >
      <View className={styles.avatarWrap}>
        <Image className={styles.avatar} src={state.headImage || process.env.__DEF_AVATAR__} />
        <Image
          className={styles.avatarCamera}
          src="/images/yikao-community/camera.png"
          onClick={() => handleUpload("headImage", "1:1")}
        />
        {state.auditStatusJson?.value !== 0 && state.headImage && (
          <View
            className={clsx(auditStyles.auditStatus, {
              [auditStyles.weigui]: state.auditStatusJson?.value === 4,
              [auditStyles.shenhezhong]:
                state.auditStatusJson?.value === 1 || state.auditStatusJson?.value === 2
            })}
          >
            {state.auditStatusJson?.value === 4 && (
              <Image
                src="/images/yikao-community/info.png"
                className={auditStyles.auditStatusIcon}
              />
            )}
            {state.auditStatusJson?.name}
          </View>
        )}
      </View>
      <View className={styles.list}>
        <View className={clsx(styles.listItem, styles.listItemInput)}>
          <View className={styles.listItemLabel}>姓名</View>
          <Input
            className={clsx(styles.showText, styles.input)}
            value={state.nickName}
            onInput={ev => setState({ nickName: ev.detail.value })}
          />
          <ArrowRight className={styles.settingArrow} />
        </View>
        <View className={styles.listItem} onClick={handleTapGender}>
          <View className={styles.listItemLabel}>性别</View>
          <View className={styles.showText}>{state.genderText}</View>
          <ArrowRight className={styles.settingArrow} />
        </View>
        <View className={clsx(styles.listItem, styles.listItemInput)}>
          <View className={styles.listItemLabel}>简介</View>
          <Input
            className={clsx(styles.showText, styles.input)}
            value={state.description}
            onInput={ev => setState({ description: ev.detail.value })}
          />
          <ArrowRight className={styles.settingArrow} />
        </View>
        <View className={styles.listItem} onClick={handleTapYears}>
          <View className={styles.listItemLabel}>
            <Text className={styles.requiredMask}>*</Text>高考年份
          </View>
          <View className={styles.showText}>{state.yearText}</View>
          <ArrowRight className={styles.settingArrow} />
        </View>
        <Picker
          mode="multiSelector"
          value={state.pendingAreaValue}
          range={state.areaOptions}
          rangeKey="title"
          onChange={handleAreaChange}
          onColumnChange={handleAreaColumnChange}
          onCancel={handleAreaCancel}
        >
          <View className={styles.listItem}>
            <View className={styles.listItemLabel}>
              <Text className={styles.requiredMask}>*</Text>高考地区
            </View>
            <View className={styles.showText}>{state.areaName}</View>
            <ArrowRight className={styles.settingArrow} />
          </View>
        </Picker>
        <Picker
          mode="selector"
          value={state.projectValue}
          range={state.projectOptions}
          rangeKey="label"
          onChange={ev => handleProjectChange(ev.detail.value)}
        >
          <View className={styles.listItem}>
            <View className={styles.listItemLabel}>
              <Text className={styles.requiredMask}>*</Text>艺考方向
            </View>
            <View className={styles.showText}>{state.projectName}</View>
            <ArrowRight className={styles.settingArrow} />
          </View>
        </Picker>
        <View className={styles.listItem}>
          <View className={styles.listItemLabel}>绑定手机</View>
          <View className={clsx(styles.showText, styles.mobilePhone)}>
            <Button
              type="default"
              openType="getPhoneNumber"
              onGetPhoneNumber={handleGetPhoneNumber}
              className={styles.phoneBtn}
            >
              {state.mobile ? state.mobile : "点击获取手机号"}
            </Button>
          </View>
          <ArrowRight className={styles.settingArrow} />
        </View>
        <View
          className={styles.listItem}
          style={{
            borderBottom: "none"
          }}
        >
          <View className={styles.listItemLabel}>背景图</View>
          <View
            className={clsx(styles.showText, styles.bgImageText)}
            onClick={() => handleUpload("backgroundImage", "4:3")}
          >
            {state.auditStatusJson?.value !== 0 && state.backgroundImage && (
              <View
                className={clsx(
                  auditStyles.auditStatus,
                  {
                    [auditStyles.weigui]: state.auditStatusJson?.value === 4,
                    [auditStyles.shenhezhong]:
                      state.auditStatusJson?.value === 1 || state.auditStatusJson?.value === 2
                  },
                  auditStyles.auditStatusBg
                )}
              >
                {state.auditStatusJson?.value === 4 && (
                  <Image
                    src="/images/yikao-community/info.png"
                    className={auditStyles.auditStatusIcon}
                  />
                )}
                {state.auditStatusJson?.name}
              </View>
            )}
            {state.backgroundImage ? (
              <Image className={styles.bgImage} src={state.backgroundImage} />
            ) : null}
          </View>
          <ArrowRight
            className={styles.settingArrow}
            onClick={() => handleUpload("backgroundImage", "4:3")}
          />
        </View>
      </View>
      <View className={styles.UnknownBtn} onClick={handleSave}>
        保存
      </View>
    </GpContainer>
  )
}
